package ch.nostromo.tiffanys.engines.tiffanys.board;

import ch.nostromo.tiffanys.game.board.BoardTools;
import ch.nostromo.tiffanys.game.move.MoveInput;

public class TiffanysMove implements Comparable<TiffanysMove> {

  public static final int CASTLING_NO = 0;

  public static final int CASTLING_SHORT = 1;

  public static final int CASTLING_LONG = 2;

  public static final int SORT_MODE_NORMAL = 0;

  public static final int SORT_MODE_HIT_SCORE = 1;

  public static int sortMode = SORT_MODE_NORMAL;

  public int from = -1;

  public int to = -1;

  public int startingPiece = -1;

  public int endingPiece = -1;

  public boolean enPassantMove = false;

  public int enPassantOpponentTake = -1;

  public int leavingEnPassantField = -1;

  public int castling = CASTLING_NO;

  public int castlingRook = -1;

  public int score = 0;

  public int scoreDepth = 0;

  public long backupEpField = -1;
  public long backupFrom = -1;
  public long backupTo = -1;
  public long backupEpTakenField = 0;
  public long backupWhiteKing = -1;
  public long backupBlackKing = -1;
  public long backupWhiteMaterial = -1;
  public long backupBlackMaterial = -1;
  public long backupCastlingRook = -1;
  public long backupCastlingRookTo = -1;
  public long backupCastelingWhite = -1;
  public long backupCastelingBlack = -1;

  public long backupZobrist = -1;

  public TiffanysMove[] scoredMoveTree = null;

  public boolean hitmove;

  public int hitScore;

  public boolean isSet = false;

  public TiffanysMove() {
    isSet = false;
  }

  private void init() {

    from = -1;

    to = -1;

    startingPiece = -1;

    endingPiece = -1;

    enPassantMove = false;

    enPassantOpponentTake = -1;

    leavingEnPassantField = -1;

    castling = CASTLING_NO;

    castlingRook = -1;

    score = 0;

    scoreDepth = 0;

    backupEpField = -1;
    backupFrom = -1;
    backupTo = -1;
    backupEpTakenField = 0;
    backupWhiteKing = -1;
    backupBlackKing = -1;
    backupWhiteMaterial = -1;
    backupBlackMaterial = -1;
    backupCastlingRook = -1;
    backupCastlingRookTo = -1;
    backupCastelingWhite = -1;
    backupCastelingBlack = -1;

    backupZobrist = -1;

  //  TiffanysMove[] scoredMoveTree = null;

    hitmove = false;

    hitScore = 0;

  }

  public void setMove(int from, int to, int startingPiece, int endingPiece, int leavingEnPassantField) {
    init();
    this.from = from;
    this.to = to;
    this.startingPiece = startingPiece;
    this.endingPiece = endingPiece;
    this.leavingEnPassantField = leavingEnPassantField;
    this.isSet = true;
  }

  public void setMove(int from, int to, int startingPiece, int endingPiece) {
    setMove(from, to, startingPiece, endingPiece, -1);
  }

  public void setMove(int from, int to, int startingPiece) {
    setMove(from, to, startingPiece, startingPiece);
  }

  public boolean isCastlingLong() {
    return castling == CASTLING_LONG;
  }
  
  public boolean isCastlingShort() {
    return castling == CASTLING_SHORT;
  }
  
  public String getToString() {
    return BoardTools.fieldToCoord(to);
  }
  
  public String getFromString() {
    return BoardTools.fieldToCoord(from);
  }
  
  private static MoveInput smallConv(TiffanysMove move) {
    String fromS = BoardTools.fieldToCoord(move.from);
    String toS = BoardTools.fieldToCoord(move.to);

    MoveInput result = null;
    if (move.endingPiece == move.startingPiece) {
      result = new MoveInput(fromS, toS);
    } else {
      result = new MoveInput(fromS, toS, move.endingPiece);
    }
    return result;
  }

  public MoveInput convertToMoveInput() {
    String fromS = BoardTools.fieldToCoord(from);
    String toS = BoardTools.fieldToCoord(to);

    MoveInput result = null;
    if (endingPiece == startingPiece) {
      result = new MoveInput(fromS, toS);
    } else {
      result = new MoveInput(fromS, toS, endingPiece);
    }
    // Score
    result.setScore(score);
    result.setScoreDepth(scoreDepth);

    // Move Tree
    if (scoredMoveTree != null) {
      MoveInput[] scoreTree = new MoveInput[scoredMoveTree.length];
      for (int i = 0; i < scoreTree.length; i++) {
        if (scoredMoveTree[i] != null) {
          scoreTree[i] = smallConv(scoredMoveTree[i]);
        }
      }
      result.setScoreTree(scoreTree);
    }

    return result;
  }

  /**
   * Implements the comparable interface
   * 
   * @param o
   *          The object to compare
   * @return Standard compare values
   */
  public int compareTo(TiffanysMove o) {
    if (o == null)
      return 1;
    TiffanysMove tmp = o;

    if (tmp.score > score) {
      return 1;
    }
    if (tmp.score < score) {
      return -1;
    }

    return 0;

  }

}